<?php
namespace euser\libs;

class Packet
{
	//是否开启数据签名，服务端客户端都需要打开，打开后可以强化安全，但会降低一点性能
	const SW_DATASIGEN_FLAG = false;

	//a flag to decide if compress the packet
	//是否打开数据压缩，目前我们用的数据压缩是zlib的gzencode，压缩级别4
	const SW_DATACOMPRESS_FLAG = false;

	//salt to mixed the crc result
	//上面开关开启后，用于加密串混淆结果，请保持客户端和服务端一致
	const SW_DATASIGEN_SALT = "=&$*#@(*&%(@";

	public static function packFormat($msg = "OK", $code = 0, $data = array())
	{
		$pack = array(
			"code" => $code,
			"msg" => $msg,
			"data" => $data,
		);

		return $pack;
	}

	public static function packEncode($data, $type = "tcp")
	{

		if ($type == "tcp") {
			$sendStr = json_encode($data);

			//if compress the packet
			if (self::SW_DATACOMPRESS_FLAG == true) {
				$sendStr = gzencode($sendStr, 4);
			}

			if (self::SW_DATASIGEN_FLAG == true) {
				$signedcode = pack('N', crc32($sendStr . self::SW_DATASIGEN_SALT));
				$sendStr = pack('N', strlen($sendStr) + 4) . $signedcode . $sendStr;
			} else {
				$sendStr = pack('N', strlen($sendStr)) . $sendStr;
			}

			return $sendStr;
		} else if ($type == "http") {
			$sendStr = json_encode($data);
			return $sendStr;
		} else {
			return self::packFormat("packet type wrong", 100006);
		}

	}

	public static function packDecode($str)
	{
		$header = substr($str, 0, 4);
		$len = unpack("Nlen", $header);
		$len = $len["len"];

		if (self::SW_DATASIGEN_FLAG == true) {

			$signedcode = substr($str, 4, 4);
			$result = substr($str, 8);

			//check signed
			if (pack("N", crc32($result . self::SW_DATASIGEN_SALT)) != $signedcode) {
				return self::packFormat("Signed check error!", 100005);
			}

			$len = $len - 4;

		} else {
			$result = substr($str, 4);
		}
		if ($len != strlen($result)) {
			//结果长度不对
			echo "error length...\n";

			return self::packFormat("packet length invalid 包长度非法", 100007);
		}
		//if compress the packet
		if (self::SW_DATACOMPRESS_FLAG == true) {
			$result = gzdecode($result);
		}
		$result = json_decode($result, 1);

		return self::packFormat("OK", 0, $result);
	}
}
